package com.powernode.order.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.common.constant.RedisConstant;
import com.powernode.common.execption.PowerException;
import com.powernode.common.result.ResultCodeEnum;
import com.powernode.model.entity.order.OrderBill;
import com.powernode.model.entity.order.OrderInfo;
import com.powernode.model.entity.order.OrderMonitor;
import com.powernode.model.entity.order.OrderProfitsharing;
import com.powernode.model.enums.OrderStatus;
import com.powernode.model.form.order.OrderInfoForm;
import com.powernode.model.form.order.StartDriveForm;
import com.powernode.model.form.order.UpdateOrderBillForm;
import com.powernode.model.form.order.UpdateOrderCartForm;
import com.powernode.model.vo.order.CurrentOrderInfoVo;
import com.powernode.order.mapper.OrderBillMapper;
import com.powernode.order.mapper.OrderInfoMapper;
import com.powernode.order.mapper.OrderProfitsharingMapper;
import com.powernode.order.service.OrderInfoService;
import com.powernode.order.service.OrderMonitorService;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private OrderInfoMapper orderInfoMapper;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private OrderMonitorService orderMonitorService;

    @Resource
    private OrderBillMapper orderBillMapper;

    @Resource
    private OrderProfitsharingMapper orderProfitsharingMapper;

    /**
     * 添加订单信息
     */
    @Transactional
    @Override
    public Long addOrderInfo(OrderInfoForm orderInfoForm) {
        //创建订单对象
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(orderInfoForm, orderInfo);

        //生成订单号
        String orderNo = UUID.randomUUID().toString().replaceAll("-", "");
        orderInfo.setOrderNo(orderNo);

        //订单状态：1等待接单，2已接单，3配送员已到达，4开始配送，5结束配送，6未付款，7已付款，8订单已结束，9顾客撤单，10配送员撤单，11事故关闭，12其他
        orderInfo.setStatus(OrderStatus.WAITING_ACCEPT.getStatus());//等待接单

        //将订单信息添加到数据库中
        this.save(orderInfo);

        //记录日志 ...

        //将订单状态放入redis
        redisTemplate.opsForValue().set(RedisConstant.ORDER_ACCEPT_MARK+orderInfo.getId(),"0",RedisConstant.ORDER_ACCEPT_MARK_EXPIRES_TIME, TimeUnit.MINUTES);

        return orderInfo.getId();
    }


    /**
     * 查询订单状态
     */
    @Override
    public Integer queryOrderStatus(Long orderId){
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(OrderInfo::getStatus);//只查询状态字段
        queryWrapper.eq(OrderInfo::getId,orderId);
        OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);

        return orderInfo.getStatus();
    }


    /**
     * 配送员抢单
     */
    @Override
    public Boolean robNewOrder(Long driverId, Long orderId) {

        RLock rLock = null;
        try {
            if (!redisTemplate.hasKey(RedisConstant.ORDER_ACCEPT_MARK+orderId)){
                //若程序进入则说明当前订单 被别人抢走或顾客取消订单
                throw new PowerException(ResultCodeEnum.COB_NEW_ORDER_FAIL);
            }


            //加锁  线程1  线程2
            rLock = redissonClient.getLock(RedisConstant.ROB_NEW_ORDER_LOCK + orderId);
            //1分钟获取不到锁之后，会放弃获取锁
            boolean flag = rLock.tryLock(RedisConstant.ROB_NEW_ORDER_LOCK_WAIT_TIME, RedisConstant.ROB_NEW_ORDER_LOCK_LEASE_TIME, TimeUnit.SECONDS);

            if (flag){
                //获取到锁后会进来执行
                if (!redisTemplate.hasKey(RedisConstant.ORDER_ACCEPT_MARK+orderId)){
                    //若程序进入则说明当前订单 被别人抢走或顾客取消订单
                    throw new PowerException(ResultCodeEnum.COB_NEW_ORDER_FAIL);
                }

                //修改订单状态
                OrderInfo orderInfo = new OrderInfo();
                orderInfo.setId(orderId);
                orderInfo.setStatus(OrderStatus.ACCEPTED.getStatus());//修改订单状态为已接单
                orderInfo.setDriverId(driverId);//设置哪个配送员接单
                orderInfo.setAcceptTime(new Date());

                int num = orderInfoMapper.updateById(orderInfo);
                if (num == 0) {
                    //抢单失败
                    throw new PowerException(ResultCodeEnum.COB_NEW_ORDER_FAIL);
                }

                //删除redis中的订单信息
                redisTemplate.delete(RedisConstant.ORDER_ACCEPT_MARK+orderId);
            }


        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            //释放锁
            if (rLock.isLocked()) {
                rLock.unlock();
            }
        }



        return true;
    }


    /**
     * 查询顾客当前订单信息
     * @param customerId
     * @return
     */
    @Override
    public CurrentOrderInfoVo searchCustomerCurrentOrder(Long customerId) {
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderInfo::getCustomerId, customerId);

        //以下这些订单状态时都会自动打开订单页面
        Integer[] statusArray = {
                OrderStatus.ACCEPTED.getStatus(),
                OrderStatus.DRIVER_ARRIVED.getStatus(),
                OrderStatus.UPDATE_CART_INFO.getStatus(),
                OrderStatus.START_SERVICE.getStatus(),
                OrderStatus.END_SERVICE.getStatus(),
                OrderStatus.UNPAID.getStatus()
        };

        queryWrapper.in(OrderInfo::getStatus, statusArray);

        //降序
        queryWrapper.orderByDesc(OrderInfo::getId);
        queryWrapper.last("limit 1");//获取最新的一条数据

        OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);

        CurrentOrderInfoVo currentOrderInfoVo = new CurrentOrderInfoVo();
        if (orderInfo != null) {
            //有当前订单
            currentOrderInfoVo.setOrderId(orderInfo.getId());
            currentOrderInfoVo.setIsHasCurrentOrder(true);
            currentOrderInfoVo.setStatus(orderInfo.getStatus());
        }else {
            //没有当前进行中的订单
            currentOrderInfoVo.setIsHasCurrentOrder(false);
        }

        return currentOrderInfoVo;
    }


    /**
     * 配送员查询当前进行中的订单
     */
    @Override
    public CurrentOrderInfoVo searchDriverCurrentOrder(Long driverId) {

        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderInfo::getDriverId, driverId);

        //以下这些订单状态时都会自动打开订单页面
        Integer[] statusArray = {
                OrderStatus.ACCEPTED.getStatus(),
                OrderStatus.DRIVER_ARRIVED.getStatus(),
                OrderStatus.UPDATE_CART_INFO.getStatus(),
                OrderStatus.START_SERVICE.getStatus(),
                OrderStatus.END_SERVICE.getStatus(),
                OrderStatus.UNPAID.getStatus()
        };

        queryWrapper.in(OrderInfo::getStatus, statusArray);

        //降序
        queryWrapper.orderByDesc(OrderInfo::getId);
        queryWrapper.last("limit 1");//获取最新的一条数据

        OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);

        CurrentOrderInfoVo currentOrderInfoVo = new CurrentOrderInfoVo();
        if (orderInfo != null) {
            //有当前订单
            currentOrderInfoVo.setOrderId(orderInfo.getId());
            currentOrderInfoVo.setIsHasCurrentOrder(true);
            currentOrderInfoVo.setStatus(orderInfo.getStatus());
        }else {
            //没有当前进行中的订单
            currentOrderInfoVo.setIsHasCurrentOrder(false);
        }

        return currentOrderInfoVo;
    }


    /**
     * 配送员到达配送员位置起点
     */
    @Override
    public Boolean driverArrivedStartPoint(Long orderId, Long driverId) {
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderInfo::getId, orderId);
        queryWrapper.eq(OrderInfo::getDriverId, driverId);

        OrderInfo updateOrderInfo = new OrderInfo();
        //修改状态为已到达起始位置
        updateOrderInfo.setStatus(OrderStatus.DRIVER_ARRIVED.getStatus());
        //到达时间
        updateOrderInfo.setArriveTime(new Date());

        orderInfoMapper.update(updateOrderInfo, queryWrapper);

        return true;
    }

    /**
     * 更新车辆信息
     */
    @Override
    public Boolean updateOrderCart(UpdateOrderCartForm updateOrderCartForm) {
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(OrderInfo::getId, updateOrderCartForm.getOrderId());
        queryWrapper.eq(OrderInfo::getDriverId, updateOrderCartForm.getDriverId());

        OrderInfo updateOrderInfo = new OrderInfo();
        BeanUtils.copyProperties(updateOrderCartForm, updateOrderInfo);

        updateOrderInfo.setStatus(OrderStatus.UPDATE_CART_INFO.getStatus());

        orderInfoMapper.update(updateOrderInfo, queryWrapper);

        return true;

    }

    /**
     * 修改状态为开始配送
     */
    @Override
    public Boolean startDrive(StartDriveForm startDriveForm) {
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderInfo::getId, startDriveForm.getOrderId());
        queryWrapper.eq(OrderInfo::getDriverId, startDriveForm.getDriverId());

        OrderInfo updateOrderInfo = new OrderInfo();
        updateOrderInfo.setStatus(OrderStatus.START_SERVICE.getStatus());//修改状态为开始配送
        updateOrderInfo.setStartServiceTime(new Date());

        orderInfoMapper.update(updateOrderInfo, queryWrapper);


        //初始化监控数据
        OrderMonitor orderMonitor = new OrderMonitor();
        orderMonitor.setOrderId(startDriveForm.getOrderId());
        orderMonitorService.saveOrderMonitor(orderMonitor);

        return true;
    }


    /**
     * 计算配送员的订单数量
     */
    @Override
    public Long getOrderNumByTime(String startTime, String endTime){
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.between(OrderInfo::getStartServiceTime, startTime, endTime);

        Long count = orderInfoMapper.selectCount(queryWrapper);

        return count;
    }


    /**
     * 结束配送
     */
    @Transactional
    @Override
    public Boolean endDrive(UpdateOrderBillForm updateOrderBillForm) {
        LambdaQueryWrapper<OrderInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderInfo::getId, updateOrderBillForm.getOrderId());
        queryWrapper.eq(OrderInfo::getDriverId, updateOrderBillForm.getDriverId());

        //更新订单表
        OrderInfo updateOrderInfo = new OrderInfo();
        updateOrderInfo.setStatus(OrderStatus.END_SERVICE.getStatus());//状态改为结束配送
        updateOrderInfo.setRealAmount(updateOrderBillForm.getTotalAmount());//总金额
        updateOrderInfo.setFavourFee(updateOrderBillForm.getFavourFee());//好处费
        updateOrderInfo.setEndServiceTime(new Date());
        updateOrderInfo.setRealDistance(updateOrderBillForm.getRealDistance());//实际里程

        orderInfoMapper.update(updateOrderInfo, queryWrapper);


        //创建账单数据
        OrderBill orderBill = new OrderBill();
        BeanUtils.copyProperties(updateOrderBillForm, orderBill);
        orderBill.setPayAmount(updateOrderBillForm.getTotalAmount());
        orderBillMapper.insert(orderBill);

        //创建分账数据
        OrderProfitsharing orderProfitsharing = new OrderProfitsharing();
        BeanUtils.copyProperties(updateOrderBillForm, orderProfitsharing);

        orderProfitsharing.setRuleId(updateOrderBillForm.getProfitsharingRuleId());

        orderProfitsharingMapper.insert(orderProfitsharing);

        return true;

    }
}
